/*
 * 上海远境文化传媒有限公司 版权所有
 */
package ext.auth;

import cache.CacheHelper;
import facade.open.BaseJsonAPI;
import helper.GlobalConfig;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.CompressionCodecs;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import models.base.AdminUser;
import models.enums.ClientType;
import models.enums.OpenIdSource;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import play.Logger;
import play.Play;
import play.libs.Crypto;
import util.DateHelper;
import util.play.CookieUtility;
import util.play.RequestUtility;

import java.util.UUID;

/**
 * 用户认证用的Helper类.
 */
public class UserAuthHelper {

    /**
     * 保存用户id在sessionId中，返回sessionId用于后续请求.
     */
    public static String storeUserIdWithSessionId(AdminUser user, OpenIdSource openIdSource) {
        if (user == null) {
            return null;
        }
        AppUserInfo wxAppUserInfo = new AppUserInfo();
        wxAppUserInfo.userId = user.id;
        wxAppUserInfo.openIdSource = openIdSource;

        Logger.debug("TLQ549770: openIdSource.name()=%s", openIdSource.name());
        String sessionId = Jwts.builder()
                .setSubject(user.id)
                .setAudience(openIdSource.name())
                .setExpiration(DateHelper.afterHours(8))  // 8小时后过期
                .compressWith(CompressionCodecs.DEFLATE)
                .signWith(SignatureAlgorithm.HS512, Play.secretKey)
                .compact();

        return sessionId;
    }

    /**
     * 从JWT中得到用户信息.
     */
    public static AppUserInfo getWxAppUserInfoFromJwt(String jwt) {
        if (StringUtils.isBlank(jwt) || StringUtils.length(jwt) < 50) {
            Logger.info("TLQ269810: bad jwt key=%s, return null", jwt);
            return null;
        }
        try {
            Claims claims = Jwts.parser().setSigningKey(Play.secretKey).parseClaimsJws(jwt).getBody();
            String userId = claims.getSubject();
            String openIdSourceValue = claims.getAudience();
            AppUserInfo wxAppUserInfo = new AppUserInfo();
            wxAppUserInfo.userId = userId;
            wxAppUserInfo.openIdSource = EnumUtils.getEnum(OpenIdSource.class, openIdSourceValue);

            return wxAppUserInfo;
        } catch(Exception e) {
            return null;
        }
    }

    /**
     * 获取CSRF的cackeVKey，用于放到缓存中.
     */
    public static String getCsrfCacheKey(String sessionId) {
        return "CSRF_" + Crypto.sign(sessionId);
    }

    /**
     * 创建 CSRF cookie
     */
    public static void setupCsrfCookie(String sessionId) {
        String csrfKey = CacheHelper.getCache(getCsrfCacheKey(sessionId), () -> Crypto.sign(UUID.randomUUID().toString()));
        CookieUtility.createCookie(BaseJsonAPI.CSRF_KEY, csrfKey);
    }

    public static OpenIdSource getCurrentApiPlatform() {
        String headerPlatform = RequestUtility.getHeaderIgnoreCase(GlobalConfig.API_HEADER_PLATFORM);

        Logger.debug("TLQ546920: 接口header %s=%s", GlobalConfig.API_HEADER_PLATFORM, headerPlatform);
        return convertOpenIdSource(headerPlatform, OpenIdSource.UNDEFINE);
    }

    private static OpenIdSource convertOpenIdSource(String openIdSourceName, OpenIdSource defaultOpenIdSource) {
        if ("we_app".equalsIgnoreCase(openIdSourceName)) {
            return OpenIdSource.WXAPP; // 微信小程序
        }
        if ("wxmp".equalsIgnoreCase(openIdSourceName)) {
            return OpenIdSource.WXMP; //微信公众号
        }

        if ("wxcp".equalsIgnoreCase(openIdSourceName)) {
            return OpenIdSource.WXCP; //微信企业号
        }
        if ("wxopen".equalsIgnoreCase(openIdSourceName)) {
            return OpenIdSource.WXOPEN; //微信开放平台（Web）
        }

        if ("outlook".equalsIgnoreCase(openIdSourceName)) {
            return OpenIdSource.OUTLOOK; //Outlook
        }
        if ("password".equalsIgnoreCase(openIdSourceName)) {
            return OpenIdSource.PASSWORD; //密码登录
        }
        if ("webapp".equalsIgnoreCase(openIdSourceName)) {
            return OpenIdSource.WEBAPP; //密码登录
        }

        return defaultOpenIdSource;
    }


    public static ClientType getCurrentClientType() {
        String headerPlatform = RequestUtility.getHeaderIgnoreCase(GlobalConfig.API_HEADER_PLATFORM);

        Logger.debug("TLQ546922: 接口header %s=%s", GlobalConfig.API_HEADER_PLATFORM, headerPlatform);
        if ("we_app".equalsIgnoreCase(headerPlatform)) {
            return ClientType.WXAPP; // 微信小程序
        }
        if ("wxmp".equalsIgnoreCase(headerPlatform)) {
            return ClientType.WEIXIN; //微信公众号
        }
        if ("wxcp".equalsIgnoreCase(headerPlatform)) {
            return ClientType.WXCP; //微信企业号
        }
        if ("wxopen".equalsIgnoreCase(headerPlatform)) {
            return ClientType.WEB; //微信开放平台（Web）
        }

        if ("outlook".equalsIgnoreCase(headerPlatform)) {
            return ClientType.OUTLOOK; //Outlook
        }
        if ("password".equalsIgnoreCase(headerPlatform)) {
            return ClientType.WEB; //密码登录
        }
        if ("webapp".equalsIgnoreCase(headerPlatform)) {
            return ClientType.WEBAPP; //WEBAPP
        }
        if ("ding".equalsIgnoreCase(headerPlatform)) {
            return ClientType.DING; //WEBAPP
        }

        return ClientType.SYS;
    }
}
